<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>
  <title>dlaed6.f</title>
 <meta name="generator" content="emacs 21.3.1; htmlfontify 0.20">
<style type="text/css"><!-- 
body { background: rgb(255, 255, 255);  color: rgb(0, 0, 0);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: none; }
span.default   { background: rgb(255, 255, 255);  color: rgb(0, 0, 0);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: none; }
span.default a { background: rgb(255, 255, 255);  color: rgb(0, 0, 0);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: underline; }
span.string   { color: rgb(188, 143, 143);  background: rgb(255, 255, 255);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: none; }
span.string a { color: rgb(188, 143, 143);  background: rgb(255, 255, 255);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: underline; }
span.comment   { color: rgb(178, 34, 34);  background: rgb(255, 255, 255);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: none; }
span.comment a { color: rgb(178, 34, 34);  background: rgb(255, 255, 255);  font-style: normal;  font-weight: 500;  font-stretch: normal;  font-family: adobe-courier;  font-size: 11pt;  text-decoration: underline; }
 --></style>

 </head>
  <body>

<pre>
      SUBROUTINE <a name="DLAED6.1"></a><a href="dlaed6.f.html#DLAED6.1">DLAED6</a>( KNITER, ORGATI, RHO, D, Z, FINIT, TAU, INFO )
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  -- LAPACK routine (version 3.1) --
</span><span class="comment">*</span><span class="comment">     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
</span><span class="comment">*</span><span class="comment">     November 2006
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     .. Scalar Arguments ..
</span>      LOGICAL            ORGATI
      INTEGER            INFO, KNITER
      DOUBLE PRECISION   FINIT, RHO, TAU
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. Array Arguments ..
</span>      DOUBLE PRECISION   D( 3 ), Z( 3 )
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  Purpose
</span><span class="comment">*</span><span class="comment">  =======
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  <a name="DLAED6.19"></a><a href="dlaed6.f.html#DLAED6.1">DLAED6</a> computes the positive or negative root (closest to the origin)
</span><span class="comment">*</span><span class="comment">  of
</span><span class="comment">*</span><span class="comment">                   z(1)        z(2)        z(3)
</span><span class="comment">*</span><span class="comment">  f(x) =   rho + --------- + ---------- + ---------
</span><span class="comment">*</span><span class="comment">                  d(1)-x      d(2)-x      d(3)-x
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  It is assumed that
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        if ORGATI = .true. the root is between d(2) and d(3);
</span><span class="comment">*</span><span class="comment">        otherwise it is between d(1) and d(2)
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  This routine will be called by <a name="DLAED4.30"></a><a href="dlaed4.f.html#DLAED4.1">DLAED4</a> when necessary. In most cases,
</span><span class="comment">*</span><span class="comment">  the root sought is the smallest in magnitude, though it might not be
</span><span class="comment">*</span><span class="comment">  in some extremely rare situations.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  Arguments
</span><span class="comment">*</span><span class="comment">  =========
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  KNITER       (input) INTEGER
</span><span class="comment">*</span><span class="comment">               Refer to <a name="DLAED4.38"></a><a href="dlaed4.f.html#DLAED4.1">DLAED4</a> for its significance.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  ORGATI       (input) LOGICAL
</span><span class="comment">*</span><span class="comment">               If ORGATI is true, the needed root is between d(2) and
</span><span class="comment">*</span><span class="comment">               d(3); otherwise it is between d(1) and d(2).  See
</span><span class="comment">*</span><span class="comment">               <a name="DLAED4.43"></a><a href="dlaed4.f.html#DLAED4.1">DLAED4</a> for further details.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  RHO          (input) DOUBLE PRECISION
</span><span class="comment">*</span><span class="comment">               Refer to the equation f(x) above.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  D            (input) DOUBLE PRECISION array, dimension (3)
</span><span class="comment">*</span><span class="comment">               D satisfies d(1) &lt; d(2) &lt; d(3).
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  Z            (input) DOUBLE PRECISION array, dimension (3)
</span><span class="comment">*</span><span class="comment">               Each of the elements in z must be positive.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  FINIT        (input) DOUBLE PRECISION
</span><span class="comment">*</span><span class="comment">               The value of f at 0. It is more accurate than the one
</span><span class="comment">*</span><span class="comment">               evaluated inside this routine (if someone wants to do
</span><span class="comment">*</span><span class="comment">               so).
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  TAU          (output) DOUBLE PRECISION
</span><span class="comment">*</span><span class="comment">               The root of the equation f(x).
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  INFO         (output) INTEGER
</span><span class="comment">*</span><span class="comment">               = 0: successful exit
</span><span class="comment">*</span><span class="comment">               &gt; 0: if INFO = 1, failure to converge
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  Further Details
</span><span class="comment">*</span><span class="comment">  ===============
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  30/06/99: Based on contributions by
</span><span class="comment">*</span><span class="comment">     Ren-Cang Li, Computer Science Division, University of California
</span><span class="comment">*</span><span class="comment">     at Berkeley, USA
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  10/02/03: This version has a few statements commented out for thread safety
</span><span class="comment">*</span><span class="comment">     (machine parameters are computed on each entry). SJH.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  05/10/06: Modified from a new version of Ren-Cang Li, use
</span><span class="comment">*</span><span class="comment">     Gragg-Thornton-Warner cubic convergent scheme for better stability.
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">  =====================================================================
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     .. Parameters ..
</span>      INTEGER            MAXIT
      PARAMETER          ( MAXIT = 40 )
      DOUBLE PRECISION   ZERO, ONE, TWO, THREE, FOUR, EIGHT
      PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
     $                   THREE = 3.0D0, FOUR = 4.0D0, EIGHT = 8.0D0 )
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. External Functions ..
</span>      DOUBLE PRECISION   <a name="DLAMCH.89"></a><a href="dlamch.f.html#DLAMCH.1">DLAMCH</a>
      EXTERNAL           <a name="DLAMCH.90"></a><a href="dlamch.f.html#DLAMCH.1">DLAMCH</a>
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. Local Arrays ..
</span>      DOUBLE PRECISION   DSCALE( 3 ), ZSCALE( 3 )
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. Local Scalars ..
</span>      LOGICAL            SCALE
      INTEGER            I, ITER, NITER
      DOUBLE PRECISION   A, B, BASE, C, DDF, DF, EPS, ERRETM, ETA, F,
     $                   FC, SCLFAC, SCLINV, SMALL1, SMALL2, SMINV1,
     $                   SMINV2, TEMP, TEMP1, TEMP2, TEMP3, TEMP4, 
     $                   LBD, UBD
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. Intrinsic Functions ..
</span>      INTRINSIC          ABS, INT, LOG, MAX, MIN, SQRT
<span class="comment">*</span><span class="comment">     ..
</span><span class="comment">*</span><span class="comment">     .. Executable Statements ..
</span><span class="comment">*</span><span class="comment">
</span>      INFO = 0
<span class="comment">*</span><span class="comment">
</span>      IF( ORGATI ) THEN
         LBD = D(2)
         UBD = D(3)
      ELSE
         LBD = D(1)
         UBD = D(2)
      END IF
      IF( FINIT .LT. ZERO )THEN
         LBD = ZERO
      ELSE
         UBD = ZERO 
      END IF
<span class="comment">*</span><span class="comment">
</span>      NITER = 1
      TAU = ZERO
      IF( KNITER.EQ.2 ) THEN
         IF( ORGATI ) THEN
            TEMP = ( D( 3 )-D( 2 ) ) / TWO
            C = RHO + Z( 1 ) / ( ( D( 1 )-D( 2 ) )-TEMP )
            A = C*( D( 2 )+D( 3 ) ) + Z( 2 ) + Z( 3 )
            B = C*D( 2 )*D( 3 ) + Z( 2 )*D( 3 ) + Z( 3 )*D( 2 )
         ELSE
            TEMP = ( D( 1 )-D( 2 ) ) / TWO
            C = RHO + Z( 3 ) / ( ( D( 3 )-D( 2 ) )-TEMP )
            A = C*( D( 1 )+D( 2 ) ) + Z( 1 ) + Z( 2 )
            B = C*D( 1 )*D( 2 ) + Z( 1 )*D( 2 ) + Z( 2 )*D( 1 )
         END IF
         TEMP = MAX( ABS( A ), ABS( B ), ABS( C ) )
         A = A / TEMP
         B = B / TEMP
         C = C / TEMP
         IF( C.EQ.ZERO ) THEN
            TAU = B / A
         ELSE IF( A.LE.ZERO ) THEN
            TAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
         ELSE
            TAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
         END IF
         IF( TAU .LT. LBD .OR. TAU .GT. UBD )
     $      TAU = ( LBD+UBD )/TWO
         TEMP = FINIT + TAU*Z(1)/( D(1)*( D( 1 )-TAU ) ) +
     $                  TAU*Z(2)/( D(2)*( D( 2 )-TAU ) ) +
     $                  TAU*Z(3)/( D(3)*( D( 3 )-TAU ) )
         IF( TEMP .LE. ZERO )THEN
            LBD = TAU
         ELSE
            UBD = TAU
         END IF
         IF( ABS( FINIT ).LE.ABS( TEMP ) )
     $      TAU = ZERO
      END IF
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     get machine parameters for possible scaling to avoid overflow
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     modified by Sven: parameters SMALL1, SMINV1, SMALL2,
</span><span class="comment">*</span><span class="comment">     SMINV2, EPS are not SAVEd anymore between one call to the
</span><span class="comment">*</span><span class="comment">     others but recomputed at each call
</span><span class="comment">*</span><span class="comment">
</span>      EPS = <a name="DLAMCH.168"></a><a href="dlamch.f.html#DLAMCH.1">DLAMCH</a>( <span class="string">'Epsilon'</span> )
      BASE = <a name="DLAMCH.169"></a><a href="dlamch.f.html#DLAMCH.1">DLAMCH</a>( <span class="string">'Base'</span> )
      SMALL1 = BASE**( INT( LOG( <a name="DLAMCH.170"></a><a href="dlamch.f.html#DLAMCH.1">DLAMCH</a>( <span class="string">'SafMin'</span> ) ) / LOG( BASE ) /
     $         THREE ) )
      SMINV1 = ONE / SMALL1
      SMALL2 = SMALL1*SMALL1
      SMINV2 = SMINV1*SMINV1
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     Determine if scaling of inputs necessary to avoid overflow
</span><span class="comment">*</span><span class="comment">     when computing 1/TEMP**3
</span><span class="comment">*</span><span class="comment">
</span>      IF( ORGATI ) THEN
         TEMP = MIN( ABS( D( 2 )-TAU ), ABS( D( 3 )-TAU ) )
      ELSE
         TEMP = MIN( ABS( D( 1 )-TAU ), ABS( D( 2 )-TAU ) )
      END IF
      SCALE = .FALSE.
      IF( TEMP.LE.SMALL1 ) THEN
         SCALE = .TRUE.
         IF( TEMP.LE.SMALL2 ) THEN
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        Scale up by power of radix nearest 1/SAFMIN**(2/3)
</span><span class="comment">*</span><span class="comment">
</span>            SCLFAC = SMINV2
            SCLINV = SMALL2
         ELSE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        Scale up by power of radix nearest 1/SAFMIN**(1/3)
</span><span class="comment">*</span><span class="comment">
</span>            SCLFAC = SMINV1
            SCLINV = SMALL1
         END IF
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        Scaling up safe because D, Z, TAU scaled elsewhere to be O(1)
</span><span class="comment">*</span><span class="comment">
</span>         DO 10 I = 1, 3
            DSCALE( I ) = D( I )*SCLFAC
            ZSCALE( I ) = Z( I )*SCLFAC
   10    CONTINUE
         TAU = TAU*SCLFAC
         LBD = LBD*SCLFAC
         UBD = UBD*SCLFAC
      ELSE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        Copy D and Z to DSCALE and ZSCALE
</span><span class="comment">*</span><span class="comment">
</span>         DO 20 I = 1, 3
            DSCALE( I ) = D( I )
            ZSCALE( I ) = Z( I )
   20    CONTINUE
      END IF
<span class="comment">*</span><span class="comment">
</span>      FC = ZERO
      DF = ZERO
      DDF = ZERO
      DO 30 I = 1, 3
         TEMP = ONE / ( DSCALE( I )-TAU )
         TEMP1 = ZSCALE( I )*TEMP
         TEMP2 = TEMP1*TEMP
         TEMP3 = TEMP2*TEMP
         FC = FC + TEMP1 / DSCALE( I )
         DF = DF + TEMP2
         DDF = DDF + TEMP3
   30 CONTINUE
      F = FINIT + TAU*FC
<span class="comment">*</span><span class="comment">
</span>      IF( ABS( F ).LE.ZERO )
     $   GO TO 60
      IF( F .LE. ZERO )THEN
         LBD = TAU
      ELSE
         UBD = TAU
      END IF
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">        Iteration begins -- Use Gragg-Thornton-Warner cubic convergent
</span><span class="comment">*</span><span class="comment">                            scheme
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     It is not hard to see that
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">           1) Iterations will go up monotonically
</span><span class="comment">*</span><span class="comment">              if FINIT &lt; 0;
</span><span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">           2) Iterations will go down monotonically
</span><span class="comment">*</span><span class="comment">              if FINIT &gt; 0.
</span><span class="comment">*</span><span class="comment">
</span>      ITER = NITER + 1
<span class="comment">*</span><span class="comment">
</span>      DO 50 NITER = ITER, MAXIT
<span class="comment">*</span><span class="comment">
</span>         IF( ORGATI ) THEN
            TEMP1 = DSCALE( 2 ) - TAU
            TEMP2 = DSCALE( 3 ) - TAU
         ELSE
            TEMP1 = DSCALE( 1 ) - TAU
            TEMP2 = DSCALE( 2 ) - TAU
         END IF
         A = ( TEMP1+TEMP2 )*F - TEMP1*TEMP2*DF
         B = TEMP1*TEMP2*F
         C = F - ( TEMP1+TEMP2 )*DF + TEMP1*TEMP2*DDF
         TEMP = MAX( ABS( A ), ABS( B ), ABS( C ) )
         A = A / TEMP
         B = B / TEMP
         C = C / TEMP
         IF( C.EQ.ZERO ) THEN
            ETA = B / A
         ELSE IF( A.LE.ZERO ) THEN
            ETA = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
         ELSE
            ETA = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) )
         END IF
         IF( F*ETA.GE.ZERO ) THEN
            ETA = -F / DF
         END IF
<span class="comment">*</span><span class="comment">
</span>         TAU = TAU + ETA
         IF( TAU .LT. LBD .OR. TAU .GT. UBD )
     $      TAU = ( LBD + UBD )/TWO 
<span class="comment">*</span><span class="comment">
</span>         FC = ZERO
         ERRETM = ZERO
         DF = ZERO
         DDF = ZERO
         DO 40 I = 1, 3
            TEMP = ONE / ( DSCALE( I )-TAU )
            TEMP1 = ZSCALE( I )*TEMP
            TEMP2 = TEMP1*TEMP
            TEMP3 = TEMP2*TEMP
            TEMP4 = TEMP1 / DSCALE( I )
            FC = FC + TEMP4
            ERRETM = ERRETM + ABS( TEMP4 )
            DF = DF + TEMP2
            DDF = DDF + TEMP3
   40    CONTINUE
         F = FINIT + TAU*FC
         ERRETM = EIGHT*( ABS( FINIT )+ABS( TAU )*ERRETM ) +
     $            ABS( TAU )*DF
         IF( ABS( F ).LE.EPS*ERRETM )
     $      GO TO 60
         IF( F .LE. ZERO )THEN
            LBD = TAU
         ELSE
            UBD = TAU
         END IF
   50 CONTINUE
      INFO = 1
   60 CONTINUE
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     Undo scaling
</span><span class="comment">*</span><span class="comment">
</span>      IF( SCALE )
     $   TAU = TAU*SCLINV
      RETURN
<span class="comment">*</span><span class="comment">
</span><span class="comment">*</span><span class="comment">     End of <a name="DLAED6.321"></a><a href="dlaed6.f.html#DLAED6.1">DLAED6</a>
</span><span class="comment">*</span><span class="comment">
</span>      END

</pre>

 </body>
</html>
